﻿using Framework.Infrastructure.Cache.Redis;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml;

namespace Framework.Infrastructure
{
    /// <summary>
    /// 通用帮助类
    /// </summary>
    public class Common
    {
        private static char[] constant = {   
            '0',/*'1',*/'2','3','4','5','6','7','8','9',  
            'a','b','c','d','e','f','g','h','i','j','k',/*'l',*/'m','n','o','p','q','r','s','t','u','v','w','x','y','z',   
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'   
                                         };

        /// <summary>
        /// 获取真实IP
        /// </summary>
        /// <returns></returns>
        public static string GetIp()
        {
            if (null == HttpContext.Current.Request.ServerVariables["HTTP_VIA"])//是否使用代理服务器
            {
                return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];//采用REMOTE_ADDR这种方法
            }
            else
            {
                return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];//采用HTTP_X-FORWARDED_FOR这种方法
            }
        }

        #region 配置文件CRUD
        /// <summary>
        /// 获取AppSetting
        /// </summary>
        /// <param name="key">键</param>
        /// <returns></returns>
        public static string GetAppSetting(string key)
        {
            string setting = ConfigurationManager.AppSettings[key];
            if (setting == null)
                return "";
            else
                return setting.ToString().Trim();
        }

        /// <summary>  
        /// 修改AppSetting
        /// </summary>  
        /// <param name="key">要修改的Key</param>  
        /// <param name="value">要修改为的值</param>  
        public static void SetAppSetting(string key, string value)
        {
            ConfigurationManager.AppSettings.Set(key, value);
        }

        /// <summary>  
        /// 添加AppSetting
        /// </summary>  
        /// <param name="key">Key</param>  
        /// <param name="value">Value</param>  
        public static void AddAppSetting(string key, string value)
        {
            ConfigurationManager.AppSettings.Add(key, value);
        }

        /// <summary>  
        /// 删除AppSetting
        /// </summary>  
        /// <param name="key">Key</param>  
        public static void RemoveAppSetting(string key)
        {
            ConfigurationManager.AppSettings.Remove(key);
        }
        #endregion

        #region XML配置文件获取节点
        /// <summary>
        /// 获取XML配置文件
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string GetXMLSetting(string path, string node)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path);
            XmlNode xn = doc.SelectSingleNode("Root").SelectSingleNode(node);
            return xn.InnerText;
        }
        #endregion

        #region DES加密解密
        /// <summary>   
        /// 加密
        /// </summary>   
        /// <param name="Text"></param>   
        /// <param name="sKey"></param>   
        /// <returns></returns>   
        public static string DesEncrypt(string Text)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray;
            inputByteArray = Encoding.Default.GetBytes(Text);
            des.Key = ASCIIEncoding.ASCII.GetBytes(ToMD5(PublicConst.DesKey).Substring(0, 8));
            des.IV = ASCIIEncoding.ASCII.GetBytes(ToMD5(PublicConst.DesKey).Substring(0, 8));
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                ret.AppendFormat("{0:X2}", b);
            }
            return ret.ToString();
        }

        /// <summary>   
        /// 解密
        /// </summary>   
        /// <param name="Text"></param>   
        /// <param name="sKey"></param>   
        /// <returns></returns>   
        public static string DesDecrypt(string Text)
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            int len;
            len = Text.Length / 2;
            byte[] inputByteArray = new byte[len];
            int x, i;
            for (x = 0; x < len; x++)
            {
                i = Convert.ToInt32(Text.Substring(x * 2, 2), 16);
                inputByteArray[x] = (byte)i;
            }
            des.Key = ASCIIEncoding.ASCII.GetBytes(ToMD5(PublicConst.DesKey).Substring(0, 8));
            des.IV = ASCIIEncoding.ASCII.GetBytes(ToMD5(PublicConst.DesKey).Substring(0, 8));
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            return Encoding.Default.GetString(ms.ToArray());
        }
        #endregion

        #region 获取可空类型的类型
        public static Type GetUnNullableType(Type conversionType)
        {
            if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                //如果是泛型方法，且泛型类型为Nullable<>则视为可空类型
                //并使用NullableConverter转换器进行转换
                var nullableConverter = new System.ComponentModel.NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            }
            return conversionType;
        }
        #endregion

        /// <summary>
        /// 截取字符串
        /// </summary>
        /// <param name="origin"></param>
        /// <param name="maxLength"></param>
        /// <returns></returns>
        public static string MaxSubstring(string str, int maxLength)
        {
            return str.Length >= maxLength ? str.Substring(0, maxLength) : str;
        }

        /// <summary>
        /// MD5
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ToMD5(string str)
        {
            if (string.IsNullOrWhiteSpace(str))
            {
                return string.Empty;
            }
            MD5 md5Hash = MD5.Create();
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str));

            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }

        /// <summary>
        /// 获取请求的GET或POST参数
        /// </summary>
        /// <returns></returns>
        public static string GetPostParas()
        {
            string param = string.Empty;
            if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
            {
                param += "[POST] ";
                for (int i = 0; i < HttpContext.Current.Request.Form.Count; i++)
                {
                    param += HttpContext.Current.Request.Form.Keys[i] + ":" + HttpContext.Current.Request.Form[i] + " ";
                }
            }
            else
            {
                param += "[GET] ";
                for (int i = 0; i < HttpContext.Current.Request.QueryString.Count; i++)
                {
                    param += HttpContext.Current.Request.QueryString.Keys[i] + ":" + HttpContext.Current.Request.QueryString[i] + " ";
                }
            }
            return param.Trim();
        }

        /// <summary>
        /// 转UTC时间
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static Int64 GetUTCTime(DateTime dt)
        {
            return (dt.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
        }

        #region JWT加密解密
        /// <summary>
        /// JWT加密（后台）
        /// </summary>
        /// <returns></returns>
        public static string JWTEncodeBKUserInfo(BKTokenModel model)
        {
            string secret = PublicConst.JWTSecretBK;
            var payload = new Dictionary<string, dynamic>
                                                { 
                                                  { "Id", model.Id }, 
                                                  { "UserName", model.UserName }, 
                                                  { "UserRealName", model.UserRealName },
                                                  { "IsSuperAdmin", model.IsSuperAdmin },
                                                  { "UTCTime", GetUTCTime(DateTime.Now) }
                                                };
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

            return encoder.Encode(payload, secret);
        }

        /// <summary>
        /// JWT加密（手机端）
        /// </summary>
        /// <returns></returns>
        public static string JWTEncodePhoneUserInfo(PhoneTokenModel model)
        {
            string secret = PublicConst.JWTSecretPhone;
            var payload = new Dictionary<string, dynamic>
                                                { 
                                                  { "Id", model.Id }, 
                                                  { "UserName", model.UserName }, 
                                                  { "UTCTime", GetUTCTime(DateTime.Now) }
                                                };
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

            return encoder.Encode(payload, secret);
        }

        /// <summary>
        /// JWT解密（后台）
        /// </summary>
        /// <returns></returns>        
        public static string JWTDecodeBK(string token)
        {
            string secret = PublicConst.JWTSecretBK;
            IJsonSerializer serializer = new JsonNetSerializer();
            IDateTimeProvider provider = new UtcDateTimeProvider();
            IJwtValidator validator = new JwtValidator(serializer, provider);
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);

            return decoder.Decode(token, secret, verify: true);
        }

        /// <summary>
        /// JWT解密（手机端）
        /// </summary>
        /// <returns></returns>        
        public static string JWTDecodePhone(string token)
        {
            string secret = PublicConst.JWTSecretPhone;
            IJsonSerializer serializer = new JsonNetSerializer();
            IDateTimeProvider provider = new UtcDateTimeProvider();
            IJwtValidator validator = new JwtValidator(serializer, provider);
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);

            return decoder.Decode(token, secret, verify: true);
        }
        #endregion

        #region 随机数、验证码
        /// <summary>
        /// 随机数
        /// </summary>
        /// <param name="Length">随机数长度</param>
        /// <returns></returns>
        public static string GenerateRandomNumber(int Length)
        {
            StringBuilder newRandom = new StringBuilder(60);
            Random rd = new Random();
            for (int i = 0; i < Length; i++)
            {
                newRandom.Append(constant[rd.Next(60)]);
            }
            return newRandom.ToString();
        }

        /// <summary>
        /// 创建验证码图片
        /// </summary>
        /// <param name="validateCode">验证码</param>
        public static byte[] CreateValidateGraphic(string validateCode)
        {
            var image = new Bitmap((int)Math.Ceiling(validateCode.Length * 13.0), 22);
            var g = Graphics.FromImage(image);
            try
            {
                //生成随机生成器
                var random = new Random();
                //清空图片背景色
                g.Clear(Color.White);
                //画图片的干扰线
                for (int i = 0; i < 25; i++)
                {
                    var x1 = random.Next(image.Width);
                    var x2 = random.Next(image.Width);
                    var y1 = random.Next(image.Height);
                    var y2 = random.Next(image.Height);
                    g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
                }
                Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic));
                //string[] fontName = { "华文新魏", "宋体", "圆体", "黑体", "隶书", "Arial" };
                //var font = new Font(fontName[new Random().Next(0, validateCode.Length)], 12, (FontStyle.Bold | FontStyle.Italic));
                var brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height),
                Color.Blue, Color.DarkRed, 1.2f, true);
                g.DrawString(validateCode, font, brush, 3, 2);
                //画图片的前景干扰点
                for (var i = 0; i < 100; i++)
                {
                    var x = random.Next(image.Width);
                    var y = random.Next(image.Height);
                    image.SetPixel(x, y, Color.FromArgb(random.Next()));
                }
                //画图片的边框线
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
                //保存图片数据
                var stream = new MemoryStream();
                image.Save(stream, ImageFormat.Jpeg);
                //输出图片流
                return stream.ToArray();
            }
            finally
            {
                g.Dispose();
                image.Dispose();
            }
        }
        #endregion

        #region 解析枚举
        /// <summary>
        /// 批量解析枚举
        /// </summary>
        /// <param name="enumType">枚举</param>
        /// <param name="description">查标注特定Description的枚举，查所有本值传空</param>
        /// <returns></returns>
        public static Dictionary<string, Dictionary<int, string>> GetEnumDescriptions(Type enumType, string description = "")
        {
            FieldInfo[] fields = enumType.GetFields(BindingFlags.Static | BindingFlags.Public);
            Dictionary<int, string> dicSingle;
            Dictionary<string, Dictionary<int, string>> dic = new Dictionary<string, Dictionary<int, string>>();
            foreach (var field in fields)
            {
                var dna = (DescriptionAttribute)Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
                string key = string.Empty;
                if (dna == null || string.IsNullOrEmpty(dna.Description))
                    key = "未知分类";
                else
                    key = dna.Description;

                if (!string.IsNullOrEmpty(description) && dna.Description != description)
                    continue;

                int value = (int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null);
                if (dic.ContainsKey(key))
                    dic[key].Add(value, field.Name);
                else
                {
                    dicSingle = new Dictionary<int, string>(); dicSingle.Add(value, field.Name);
                    dic.Add(key, dicSingle);
                }
            }
            return dic;
        }

        /// <summary>
        /// 单个解析枚举
        /// </summary>
        /// <param name="enumeration"></param>
        /// <returns></returns>
        public static string GetEnumDescription(Enum enumeration)
        {
            Type type = enumeration.GetType();
            MemberInfo[] memInfo = type.GetMember(enumeration.ToString());
            if (null != memInfo && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (null != attrs && attrs.Length > 0)
                    return ((DescriptionAttribute)attrs[0]).Description;
            }
            return enumeration.ToString();
        }
        #endregion



    }
}
